/*
 * Copyright (c) Jack魏 2023 - 2024, All Rights Reserved.
 */

package cn.jackwei.yiyi.config;

import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.hutool.extra.spring.SpringUtil;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * WebMvc 配置
 *
 * @author Jack魏
 * @since 2023/11/25 22:06
 */
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Value("${yiyi.file.path}")
    private String path;

    @Value("${yiyi.file.view.path}")
    private String viewPath;

    /**
     * 映射静态文件
     *
     * @param registry 静态注册
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        /**
         * 第一个参数是创建虚拟路径/file/** ，前端使用：<img src= "/file/jack.jpg"/>便可直接引用服务器上的文件。
         * 第二个参数是图片的物理路径格式："file:" + 本地实际地址 + "/"，注意一定要以/结尾，不然不生效！
         */
        registry.addResourceHandler(viewPath).addResourceLocations("file:" + path + "/");
    }

    /**
     * 注册 Sa-Token 拦截器，打开注解式鉴权功能
     *
     * @param registry 注册信息
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        String activeProfile = SpringUtil.getActiveProfile();
        // 注册 Sa-Token 拦截器，打开注解式鉴权功能
        if (!"dev".equals(activeProfile)) {
            registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**");
        }
    }

    @Value("${spring.jackson.date-format}")
    private String jacksonDateFormat;

    /**
     * Jackson解析配置
     */
    @Bean
    @Primary
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer());

        // 后端Long类型转换成前端String类型，解决前端接收时精度丢失的问题
        javaTimeModule.addSerializer(Long.class, ToStringSerializer.instance)
                .addSerializer(Long.TYPE, ToStringSerializer.instance);
        objectMapper.registerModule(javaTimeModule);
        return objectMapper;
    }

    /**
     * LocalDateTime 前端转换
     */
    public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
        @Override
        public void serialize(LocalDateTime dateTime, JsonGenerator generator, SerializerProvider provider)
                throws IOException {
            generator.writeString(dateTime.format(DateTimeFormatter.ofPattern(jacksonDateFormat)));
        }
    }

    /**
     * LocalDateTime 后端转换
     */
    public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
        @Override
        public LocalDateTime deserialize(JsonParser parser, DeserializationContext context)
                throws IOException {
            return LocalDateTime.parse(parser.getValueAsString(), DateTimeFormatter.ofPattern(jacksonDateFormat));
        }
    }
}
